﻿
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace StructGoTest.GameObjects {

	public abstract class GameObject {

		public static Random Random = new Random();

		private const float Gravity = .5f;

		// Body
		public bool HasBody;
		public Vector2 Position;
		public bool OnSolidGround = true;

		// Think
		public bool HasMind;

		// Move
		public bool CanMove;
		public float BaseHorizontalMoveSpeed;
		public float CurrentHorizontalSpeed;
		public bool CanJump;
		public float HorizontalJumpSpeed;
		public float VerticalJumpSpeed;
		public float CurrentVerticalSpeed;
		public Direction Direction;

		// Collide


		// Draw
		public bool IsDrawable;
		public Texture2D Texture;
		public float Width;
		public float Height;
		public Color Color;

		// Head
		public bool HasHead;
		public Texture2D HeadTexture;
		public Vector2 Neck;
		public Vector2 TopOfHead;
		public Vector2 CenterOfHead;
		public float HeadAngle;
		public float RotationSpeed;
		public HeadGear HeadGear;
		public Rectangle HeadBounds;

		// Misc.
		// ...


		public virtual void Update(GameTime gameTime) {

			if (HasMind) {
				Think(gameTime);
			}

			if (CanMove) {
				Move(gameTime);
			}

			if (HasBody) {
				ApplyForces(gameTime);
				HandleCollisions();
			}

		}


		public virtual void Think(GameTime gameTime) {
			// ...
		}


		public virtual void Move(GameTime gameTime) {
			// ...
		}


		public void ApplyForces(GameTime gameTime) {
			// TODO: only if not standing on the ground.
			if (!OnSolidGround) {
				CurrentVerticalSpeed += Gravity;
			}
			float xDelta = CurrentHorizontalSpeed * (float)Direction * (float)gameTime.ElapsedGameTime.TotalSeconds;
			float yDelta = CurrentVerticalSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
			Position = new Vector2(Position.X + xDelta, Position.Y + yDelta);
		}


		public void HandleCollisions() {
			// TODO: Need a bounding box
			if (Position.Y > BlobTestGame.Floor - Height) {
				Position.Y = BlobTestGame.Floor - Height;
				OnSolidGround = true;
			}
			if (HasHead) {
				SetHeadLocation();
			}
		}

		public void SetHeadLocation() {

			HeadBounds = new Rectangle((int)Position.X, (int)Position.Y, HeadTexture.Width, HeadTexture.Height);
			CenterOfHead = new Vector2(HeadBounds.Center.X, HeadBounds.Center.Y);

			if (Direction == Direction.Left) {
				Neck = new Vector2(Position.X + Width - 10, Position.Y); // TODO: Needs to be centered.
			} else {
				Neck = new Vector2(Position.X + 10, Position.Y); // TODO: Needs to be centered.
			}

			TopOfHead = new Vector2(Neck.X, Neck.Y - HeadTexture.Height); // TODO: Needs to be centered.

			float headAngleInRadians = MathHelper.ToRadians(HeadAngle);
			TopOfHead.X = (float)(Math.Cos(headAngleInRadians) * (TopOfHead.X - CenterOfHead.X) - Math.Sin(headAngleInRadians) * (TopOfHead.Y - CenterOfHead.Y) + CenterOfHead.X);
			TopOfHead.Y = (float)(Math.Sin(headAngleInRadians) * (TopOfHead.X - CenterOfHead.X) + Math.Cos(headAngleInRadians) * (TopOfHead.Y - CenterOfHead.Y) + CenterOfHead.Y);
		}


		public virtual void Draw(GameTime gametime) {
			if (IsDrawable) {
				BlobTestGame.SpriteBatch.Draw(Texture, 
					new Rectangle((int) Position.X, (int) Position.Y, (int)Width, (int)Height),
					null,
					Color,
					0,
					Vector2.Zero,
					Direction == Direction.Right ? SpriteEffects.None : SpriteEffects.FlipHorizontally,
					0);
			}
		}

	}

}